package me.springboot.mybatis.tianyi;

import com.alibaba.fastjson.JSONObject;
import me.springboot.mybatis.common.utils.JSONUtil;
import me.springboot.mybatis.common.utils.StringUtil;
import me.springboot.mybatis.dao.ConfigMapper;
import me.springboot.mybatis.dao.CoverMapper;
import me.springboot.mybatis.dao.DeviceMapper;
import me.springboot.mybatis.enmu.DeviceTypeEnum;
import me.springboot.mybatis.model.*;
import me.springboot.mybatis.service.ConfigService;
import me.springboot.mybatis.service.DeviceService;
import me.springboot.mybatis.service.TrashDataService;
import me.springboot.mybatis.service.TrashService;
import me.springboot.mybatis.zhcs.utils.ByteUtils;
import me.springboot.mybatis.zhcs.utils.DateUtils;
import me.springboot.mybatis.zhcs.utils.IDGenerator;
import me.springboot.mybatis.zhcs.utils.NorthwardUtils;
import org.apache.log4j.Logger;
import org.apache.mina.core.buffer.IoBuffer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.UnsupportedEncodingException;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController
@RequestMapping
@CrossOrigin
public class TestController {
    private static final Logger logger = Logger.getLogger(TestController.class);

    @Autowired
    private TrashService trashService;
    @Autowired
    private TrashDataService trashDataService;
    @Autowired
    private DeviceService deviceService;
    @Autowired
    private ConfigService configService;
    @Resource
    private DeviceMapper deviceMapper;
    @Resource
    private ConfigMapper configMapper;
    @Autowired
    private CoverMapper coverMapper;


    @RequestMapping(value = "/acceptmsg", method = {RequestMethod.GET, RequestMethod.POST})
    public String acceptmsg(HttpServletRequest request) {
        try {
            logger.info("======================" + request);
            BufferedReader br = request.getReader();
            String wholeStr = "";
            String str = "";
            while ((str = br.readLine()) != null) {
                wholeStr = wholeStr + str;
            }
            logger.info("wholeStr=" + wholeStr);
            JSONObject json = JSONObject.parseObject(wholeStr);
            logger.info("json:" + json);
            str = json.getJSONObject("service").getJSONObject("data").getString("MsgInforUp");
            logger.info(str);
            IoBuffer in = ByteUtils.stringToIoBuffer(str);
            logger.info("总长度：" + in.remaining());
            byte[] bytes;
            bytes = new byte[2];
            in.get(bytes);
            //判断数据包头是否为固定0x3F - 0x3F
            logger.info(ByteUtils.BinaryToHexString(bytes));
            if (ByteUtils.BinaryToHexString(bytes).equals("3F3F")) {
                bytes = new byte[2];
                in.get(bytes);
                //帧长度
                int frameLength = ByteUtils.byte2Uint16(bytes);
                bytes = new byte[2];
                in.get(bytes);
                //指令类型
                int command_type = ByteUtils.byte2Uint16(bytes);
                logger.info(frameLength + "  " + command_type + "   length:" + in.remaining());
                //标记 跳过数据部分
                in.mark();
                bytes = new byte[frameLength - 2];
                in.get(bytes);
                logger.info("length:" + in.remaining());
                //帧校验
                bytes = new byte[2];
                in.get(bytes);
                /*int framecheck = ByteUtils.byte2Uint16(bytes);
                logger.info("帧校验:"+framecheck);*/
                bytes = new byte[2];
                in.get(bytes);
                if (ByteUtils.BinaryToHexString(bytes).equals("4040")) {
                    //验证完毕 重置回复到mark位置进行数据解析
                    in.reset();
                    decoding(in, str);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 解析
     *
     * @param in
     */
    public Map<String, Object> decoding(IoBuffer in, String str) {
        byte[] bytes;
        //数据包第一位 设备类型
        bytes = new byte[1];
        in.get(bytes);
        int command_type = Integer.parseInt(ByteUtils.BinaryToHexString(bytes));
        //环境参数上传:2 垃圾桶
        logger.info("command_type=" + command_type);
        if (command_type == 2) {
            toTrash(in, str);
        } else if (command_type == 1) {
            toCover(in, str);
        }
        return null;
    }

    /**
     * 井盖数据包解析
     *
     * @param in
     */
    private void toCover(IoBuffer in, String str) {
        byte[] bytes;
        Cover cover = new Cover();
        cover.setId(IDGenerator.getStrID());
        cover.setDeviceType(DeviceTypeEnum.JingGai.getCode());
        //程序版本号
        bytes = new byte[2];
        in.get(bytes);
        cover.setVersion(ByteUtils.BinaryToHexString(bytes));
        //设备号
        bytes = new byte[16];
        in.get(bytes);
//        cover.setDeviceid(ByteUtils.BinaryToHexString(bytes));
        String deviceId = ByteUtils.bytesToAscii(bytes, 0, bytes.length);
        logger.info("deviceId="+deviceId);
        cover.setDeviceid(deviceId);

        //设备状态
        bytes = new byte[1];
        in.get(bytes);
        String status = ByteUtils.BinaryToHexString(bytes);
        if (status.equals("1")) {
            cover.setDeviceState("1");
        } else if (status.equals("4")) {
            cover.setDeviceState("3");
        } else {
            cover.setDeviceState("2");
        }
        //保存一份原始数据
        cover.setOriginDeviceStatus(status);

        //通信传输模式
        bytes = new byte[1];
        in.get(bytes);
        cover.setMode(ByteUtils.BinaryToHexString(bytes));
        //温度（摄氏度℃*100）
        bytes = new byte[2];
        in.get(bytes);
        cover.setTemperature(ByteUtils.byte2Uint16(bytes));
        //液面高度
        bytes = new byte[2];
        in.get(bytes);
        cover.setHight(ByteUtils.byte2Uint16(bytes));
        //打开角度（°）
        bytes = new byte[2];
        in.get(bytes);
        cover.setAngle_1(ByteUtils.byte2Uint16(bytes));
        //打开角度（′）
        bytes = new byte[2];
        in.get(bytes);
        cover.setAngle_2(ByteUtils.byte2Uint16(bytes));
        //电池电量（电压 V*100）
        bytes = new byte[2];
        in.get(bytes);
        cover.setBatterylevel(ByteUtils.byte2Uint16(bytes));
        //电量（%）
        bytes = new byte[1];
        in.get(bytes);
        cover.setElectricity(ByteUtils.BinaryToHexString(bytes));
        //相对湿度（%RH）预留
        bytes = new byte[2];
        in.get(bytes);
        cover.setHumidity(ByteUtils.byte2Uint16(bytes));
        //经度（度分分格式*10000）预留
        bytes = new byte[4];
        in.get(bytes);
        cover.setLongitude(ByteUtils.byte2int(bytes));
        //纬度（度分分格式*10000）预留
        bytes = new byte[4];
        in.get(bytes);
        cover.setLatitude(ByteUtils.byte2int(bytes));
        //预留1
        bytes = new byte[2];
        in.get(bytes);
        cover.setStr1(ByteUtils.BinaryToHexString(bytes));
        //预留2
        bytes = new byte[2];
        in.get(bytes);
        cover.setStr2(ByteUtils.BinaryToHexString(bytes));
        //预留3
        bytes = new byte[4];
        in.get(bytes);
        cover.setStr3(ByteUtils.BinaryToHexString(bytes));

        cover.setAddtime(new Date().getTime());
        //存储
        logger.info("cover=" + JSONUtil.beanToJson(cover));
        int dataStatus = updateCover(cover, status);
        logger.info("dataStatus=" + dataStatus);
        cover.setDataStatus(dataStatus);
        coverMapper.insert(cover);

        try {
            NorthwardUtils.createClient(cover.getDeviceid(), str);
        } catch (Exception e) {
            logger.error("回传失败====================");
        }
    }

    private int updateCover(Cover cover, String status) {
        Device queryDevice = new Device();
        queryDevice.setEquipmentNum(cover.getDeviceid());
        List<Device> devices = deviceMapper.selectModel(queryDevice);
        int dataStatus = 1;
        if (null != devices && devices.size() > 0) {
            Device device = devices.get(0);
            cover.setLongitude(device.getLongitude());
            cover.setLatitude(device.getLatitude());
            Map<String, Object> paramMap = new HashMap<>();
            paramMap.put("devicetype", DeviceTypeEnum.JingGai.getCode());
            paramMap.put("kehu_userid", device.getKehuUserid());
            List<Config> configs = configMapper.selectByMap(paramMap);
            device.setDeviceStatus(Integer.valueOf(cover.getDeviceState()));
            device.setDevicetype(Integer.valueOf(DeviceTypeEnum.JingGai.getCode()));
            Integer angle_2 = 0;
            boolean isEques = false;
            logger.info("========================比对数据状态" + configs.size());
            for (Config config : configs) {
                if (config.getName().equals("temperature") && StringUtil.isNotBlank(config.getValue())) {
                    if (cover.getTemperature() > Integer.valueOf(config.getValue())) {
                        dataStatus = 2;
                        break;
                    }
                } else if (config.getName().equals("jinggaihight") && StringUtil.isNotBlank(config.getValue())) {
                    if (cover.getHight() > Integer.valueOf(config.getValue())) {
                        dataStatus = 2;
                        break;
                    }
                } else if (config.getName().equals("angle_1") && StringUtil.isNotBlank(config.getValue())) {
                    if (cover.getAngle_1() > Integer.valueOf(config.getValue())) {
                        dataStatus = 2;
                        break;
                    } else if (cover.getAngle_2().intValue() == Integer.valueOf(config.getValue()).intValue()) {
                        isEques = true;
                    }
                } else if (config.getName().equals("dianliang") && StringUtil.isNotBlank(config.getValue())) {
                    if (cover.getBatterylevel() > Integer.valueOf(config.getValue())) {
                        dataStatus = 2;
                        break;
                    }
                } else if (config.getName().equals("angle_2") && StringUtil.isNotBlank(config.getValue())) {
                    angle_2 = Integer.valueOf(config.getValue());
                }
            }

            if (dataStatus == 1 && isEques) {
                if (cover.getAngle_2() > angle_2) {
                    dataStatus = 2;
                }
            }
            if (status.equals("8") || status.equals("16")) {// 移位数据异常
                dataStatus = 2;
            }
            device.setDataStatus(dataStatus);
            deviceService.update(device);
        }
        return dataStatus;
    }

    private void toTrash(IoBuffer in, String str) {
        logger.info("数据包长度：" + in.remaining());
        byte[] bytes;
        Trash trash = new Trash();
        String tid = IDGenerator.getStrID();
        trash.setId(tid);
        trash.setDevicetype(DeviceTypeEnum.LaJi.getCode());
        //程序版本号
        bytes = new byte[2];
        in.get(bytes);
        trash.setVersion(ByteUtils.BinaryToHexString(bytes));
        //设备号
        String sim = "";
        String imei = "";
        String serialnumber = "";
        try {
           /* //（SIM 卡号（20）
            bytes = new byte[20];
            in.get(bytes);
            sim = new String(bytes,"utf-8");
            //IMEI 号 （15）
            bytes = new byte[15];
            in.get(bytes);
            imei = new String(bytes,"utf-8");*/
            //设备序列号（6）
            bytes = new byte[6];
            in.get(bytes);
            serialnumber = new String(bytes, "utf-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        trash.setSim(sim);
        trash.setImei(imei);
        trash.setDevicenum(serialnumber);
        //设备状态
        bytes = new byte[1];
        in.get(bytes);
        byte[] b = new byte[]{bytes[0], 0x00};
        int status = ByteUtils.byte2Uint16(b);
        if (status == 85) {
            trash.setDevicestate(1);
        } else if (status == 179) {
            trash.setDevicestate(2);
        } else {
            trash.setDevicestate(3);
        }
        //保存一份原始数据
        String originDeviceStatus = ByteUtils.BinaryToHexString(bytes);
        trash.setOriginDeviceStatus(originDeviceStatus);
//        trash.setDevicestate(ByteUtils.byte2Uint16(b));
        //报告类型
        bytes = new byte[1];
        in.get(bytes);
        b = new byte[]{bytes[0], 0x00};
        trash.setReporttype(ByteUtils.byte2Uint16(b));
        //数据包数
        bytes = new byte[2];
        in.get(bytes);
        int packageCount = ByteUtils.byte2Uint16(bytes);
        TrashData trashData = null;
        for (int i = 0; i < packageCount; i++) {
            trashData = new TrashData();
            trashData.setId(IDGenerator.getStrID());
            trashData.setTid(tid);
            //时间（年月日时分秒）年2000+X
            bytes = new byte[1];
            in.get(bytes);
            b = new byte[]{bytes[0], 0x00};
            int yyyy = 2000 + ByteUtils.byte2Uint16(b);
            //月
            bytes = new byte[1];
            in.get(bytes);
            b = new byte[]{bytes[0], 0x00};
            int mm = ByteUtils.byte2Uint16(b);
            //日
            bytes = new byte[1];
            in.get(bytes);
            b = new byte[]{bytes[0], 0x00};
            int dd = ByteUtils.byte2Uint16(b);
            //时
            bytes = new byte[1];
            in.get(bytes);
            b = new byte[]{bytes[0], 0x00};
            int HH = ByteUtils.byte2Uint16(b);
            //分
            bytes = new byte[1];
            in.get(bytes);
            b = new byte[]{bytes[0], 0x00};
            int MM = ByteUtils.byte2Uint16(b);
            //秒
            bytes = new byte[1];
            in.get(bytes);
            b = new byte[]{bytes[0], 0x00};
            int SS = ByteUtils.byte2Uint16(b);
            trashData.setDatatime(DateUtils.parseDateTimeByString(yyyy + "-" + mm + "-" + dd + " " + HH + ":" + MM + ":" + SS).getTime());
            //温度
            bytes = new byte[2];
            in.get(bytes);
            trashData.setDatatemper(ByteUtils.byte2Uint16(bytes) + "");
            //垃圾实际高度（单位 mm）
            bytes = new byte[2];
            in.get(bytes);
            trashData.setHeight(ByteUtils.byte2Uint16(bytes) + "");
            //添加数据库
            trashDataService.save(trashData);
        }
        //垃圾桶高度（单位 mm）
        bytes = new byte[2];
        in.get(bytes);
        trash.setBinheight(ByteUtils.byte2Uint16(bytes) + "");
        //首次上报水线阈值（单位 mm）
        bytes = new byte[2];
        in.get(bytes);
        trash.setFirstwaterlinethreshold(ByteUtils.byte2Uint16(bytes) + "");
        //第二次上报水线阈值（单位 mm)
        bytes = new byte[2];
        in.get(bytes);
        trash.setSecondwaterlinethreshold(ByteUtils.byte2Uint16(bytes) + "");
        //已清理阈值（单位 mm）
        bytes = new byte[2];
        in.get(bytes);
        trash.setClearedthreshold(ByteUtils.byte2Uint16(bytes) + "");
        //传输模式
        bytes = new byte[1];
        in.get(bytes);
        b = new byte[]{bytes[0], 0x00};
        trash.setMode(ByteUtils.byte2Uint16(b));
        //温度超限阈值（摄氏度℃*100）
        bytes = new byte[2];
        in.get(bytes);
        trash.setUppertemperature(ByteUtils.byte2Uint16(bytes) + "");
        //电池电量（电压 V*100）
        bytes = new byte[2];
        in.get(bytes);
        trash.setBatterylevel(ByteUtils.byte2Uint16(bytes));
        //电量（%）
        bytes = new byte[1];
        in.get(bytes);
        b = new byte[]{bytes[0], 0x00};
        trash.setElectricity(ByteUtils.byte2Uint16(b) + "");
        //相对湿度（%RH）预留
        bytes = new byte[2];
        in.get(bytes);
        trash.setHumidity(ByteUtils.byte2Uint16(bytes));
        //盖子/箱体角度（°）
        bytes = new byte[2];
        in.get(bytes);
        trash.setAngle_1(ByteUtils.byte2Uint16(bytes));
        //盖子/箱体角度（′）
        bytes = new byte[2];
        in.get(bytes);
        trash.setAngle_2(ByteUtils.byte2Uint16(bytes));
        //经度（度分分格式*10000）预留
        bytes = new byte[4];
        in.get(bytes);
        trash.setLongitude(ByteUtils.byte2int(bytes));
        //纬度（度分分格式*10000）预留
        bytes = new byte[4];
        in.get(bytes);
        trash.setLatitude(ByteUtils.byte2int(bytes));
       /* //预留1
        bytes = new byte[2];
        in.get(bytes);
        trash.setStr1(ByteUtils.BinaryToHexString(bytes));
        //预留2
        bytes = new byte[2];
        in.get(bytes);
        trash.setStr2(ByteUtils.BinaryToHexString(bytes));
        //预留3
        bytes = new byte[4];
        in.get(bytes);
        trash.setStr3(ByteUtils.BinaryToHexString(bytes));*/
        trash.setAddtime(new Date().getTime());

        logger.info("trash=" + JSONUtil.beanToJson(trash));
        int dataStatus = updateTrash(trash, trashData);
        logger.info("dataStatus=" + dataStatus);
        trash.setDataStatus(dataStatus);
        trashService.save(trash);

        try {
            NorthwardUtils.createClient(serialnumber, str);
        } catch (Exception e) {
            logger.error("回传失败====================");
        }
    }

    private int updateTrash(Trash trash, TrashData trashData) {
        Device queryDevice = new Device();
        queryDevice.setEquipmentNum(trash.getDevicenum());
        List<Device> devices = deviceMapper.selectModel(queryDevice);
        int dataStatus = 1;
        if (null != devices && devices.size() > 0) {
            Device device = devices.get(0);
            trash.setLongitude(device.getLongitude());
            trash.setLatitude(device.getLatitude());
            Config queryConfig = new Config();
            Map<String, Object> paramMap = new HashMap<>();
            paramMap.put("devicetype", DeviceTypeEnum.LaJi.getCode());
            paramMap.put("kehu_userid", device.getKehuUserid());
            List<Config> configs = configMapper.selectByMap(paramMap);
            device.setDeviceStatus(Integer.valueOf(trash.getDevicestate()));
            device.setDevicetype(Integer.valueOf(DeviceTypeEnum.LaJi.getCode()));
            for (Config config : configs) {
                if (config.getName().equals("lajiliang") && StringUtil.isNotBlank(config.getValue())) {
                    if (Integer.valueOf(trashData.getHeight()) > Integer.valueOf(config.getValue())) {
                        dataStatus = 2;
                        break;
                    }
                } else if (config.getName().equals("wendu") && StringUtil.isNotBlank(config.getValue())) {
                    if (Integer.valueOf(trashData.getDatatemper()) > Integer.valueOf(config.getValue())) {
                        dataStatus = 2;
                        break;
                    }
                } /*else if (config.getName().equals("clearedthreshold") && StringUtil.isNotBlank(config.getValue())) {
                    if (Integer.valueOf(trash.getClearedthreshold()) > Integer.valueOf(config.getValue())) {
                        dataStatus = 2;
                        break;
                    }
                }*/ else if (config.getName().equals("voltage") && StringUtil.isNotBlank(config.getValue())) {
                    if (trash.getBatterylevel() > Integer.valueOf(config.getValue())) {
                        dataStatus = 2;
                        break;
                    }
                }
            }
            device.setDataStatus(dataStatus);
            deviceService.update(device);
        }
        return dataStatus;
    }

}
